package com.hcy.rabbitmanagerapi.controller;

import com.hcy.rabbitbasicmodel.enums.Clients;
import com.hcy.rabbitbasicmodel.enums.Log_Code;
import com.hcy.rabbitbasicmodel.model.ResponseData;
import com.hcy.rabbitbasicmodel.model.ReturnResult;
import com.hcy.rabbitbasicmodel.model.TokenService;
import com.hcy.rabbitbasicutils.utils.MyHttpUtils;
import com.hcy.rabbitmanagerapi.model.UserInfo;
import com.hcy.rabbitmanagerapi.utils.CheckTokenAccess;
import com.hcy.rabbitmanagerapi.utils.MyAutoOptLog;
import com.hcy.userclient.client.UserAuthClient;
import com.hcy.usermodel.dto.request.UserAuthRequestDTO;
import com.hcy.usermodel.dto.response.ManagerPermissionResponseDTO;
import com.hcy.usermodel.dto.response.UserAuthsResponseDTO;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport;
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

@RestController
public class LoginController {
    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Value("${security.oauth2.client.access-token-uri}")
    private String accessTokenUri;
    @Value("${security.oauth2.client.client-id}")
    private String clientId;
    @Value("${security.oauth2.client.client-secret}")
    private String clientSecret;
    @Autowired
    MyHttpUtils myHttpUtils;
    @Autowired
    CheckTokenAccess checkTokenAccess;
    @Autowired
    UserAuthClient userAuthClient;

    @PostMapping("/login")
//    @MyAutoOptLog(Log_Code.DEFAULT)
    public ReturnResult login(@RequestBody UserAuthRequestDTO user) {
        logger.info("login start param -> {}", ToStringBuilder.reflectionToString(user));
        //OAuth2AccessToken
        if (StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword())) {
            return ReturnResult.fail("用户名和密码不能为空");
        }
        String username = user.getUsername();
        String password = user.getPassword();
        // 创建 ResourceOwnerPasswordResourceDetails 对象
        ResourceOwnerPasswordResourceDetails resourceDetails = new ResourceOwnerPasswordResourceDetails();
        resourceDetails.setAccessTokenUri(accessTokenUri);
        resourceDetails.setClientId(clientId);
        resourceDetails.setClientSecret(clientSecret);
        //处理用户名，携带更多信息 导致refresh_token 出现问题 bug
        username = username + "+" + "manager";
        resourceDetails.setUsername(username);
        resourceDetails.setPassword(password);
        // 创建 OAuth2RestTemplate 对象
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails);
        restTemplate.setAccessTokenProvider(new ResourceOwnerPasswordAccessTokenProvider());
        try {
            OAuth2AccessToken accessToken = restTemplate.getAccessToken();
            return ReturnResult.success("认证成功！").setData(accessToken);
        } catch (Exception e) {
            return ReturnResult.fail("用户名或密码错误！");
        }
    }

    @PostMapping("/refresh_token")
    public ReturnResult refreshToken(@RequestBody TokenService tokenService) {
        logger.info("refresh_token start param -> {}", ToStringBuilder.reflectionToString(tokenService));
        try {
            MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
            MultiValueMap<String, String> header = new LinkedMultiValueMap<>();
            map.add("grant_type", "refresh_token");
            map.add("refresh_token", tokenService.getRefreshToken());
            map.add("client_id", clientId);
            map.add("client_secret", clientSecret);
            header.add("business", "driver");
            ReturnResult returnResult = myHttpUtils.sendPostRequest(accessTokenUri, map, header);
            if (returnResult.getCode() == 200) {
                return returnResult;
            } else {
                return ReturnResult.fail("刷新token失败");
            }
        } catch (Exception e) {
            return ReturnResult.fail("会话已过期请重新登录！");
        }
    }

    @PostMapping("/check_token")
    public ReturnResult checkToken(@RequestBody TokenService tokenService) {
        logger.info("checkToken start param -> {}", ToStringBuilder.reflectionToString(tokenService));
        HashMap<String, String> stringStringHashMap = checkTokenAccess.checkToken(tokenService.getToken());
        if (stringStringHashMap == null) {
            return ReturnResult.fail("会话已过期请重新登录！");
        } else {
            return ReturnResult.success("有效token").setData(stringStringHashMap);
        }
    }

    /**
     * @Author huchenying
     * @Description TODO 通过token获取用户角色权限和基础信息
     * @Date 2022/4/20 19:41
     **/
    @PostMapping("/getInfo")
    public ReturnResult getInfo(@Validated @RequestBody TokenService token){
        logger.info("getInfo start param -> {}",ToStringBuilder.reflectionToString(token));
        String username = checkTokenAccess.getUsernameByToken(token.getToken());
        if(username == null){
            ReturnResult returnResult = new ReturnResult();
            returnResult.setCode(401);
            returnResult.setMsg("无效token，请重新登录！");
            return returnResult;
        }
        //调用user获取用户信息
        UserAuthRequestDTO userAuthRequestDTO = new UserAuthRequestDTO();
        userAuthRequestDTO.setUsername(username);
        userAuthRequestDTO.setBusinessCode(Clients.MANAGER.getName());
        ResponseData<ManagerPermissionResponseDTO> userPermissionInfo = userAuthClient.getUserPermissionInfo(userAuthRequestDTO);
        if(userPermissionInfo.getCode().noSuccess()){
            ReturnResult returnResult = new ReturnResult();
            returnResult.setCode(400);
            returnResult.setMsg("拉取权限失败");
            return returnResult;
        }
        ManagerPermissionResponseDTO data = userPermissionInfo.getData();
        //返回信息
        return ReturnResult.success().setData(data);
    }
}
